﻿using System;
using System.Linq.Expressions;
using NMapper.Utils;

namespace NMapper.Mappings
{
    public class EntityRefMapping<TDatabase, TParentDbEntity, TChildDbId, TChildDbEntity, TParentOutput, TChildOutput> : EntityMapping<TDatabase, TParentDbEntity, TChildDbEntity, TParentOutput, TChildOutput> 
        where TChildDbEntity : class
        where TDatabase : IDisposable
        where TChildOutput : class
    {
        private Expression<Func<MapContext<TDatabase>, TParentDbEntity, TChildDbId>> dbIdSelector;
        private Func<MapContext<TDatabase>, TParentDbEntity, TChildDbId> dbIdSelectorFunc;

        public EntityRefMapping(Expression<Func<MapContext<TDatabase>, TParentDbEntity, TChildDbId>> dbIdSelector, Expression<Func<MapContext<TDatabase>, TParentDbEntity, TChildDbEntity>> dbSelector, Expression<Func<TParentOutput, TChildOutput>> outputSelector, Mapper<TDatabase, TChildDbEntity, TChildOutput> mapper)
            : base(dbSelector, outputSelector, mapper)
        {
            this.dbIdSelector = dbIdSelector;
            dbIdSelectorFunc = dbIdSelector.Compile();
        }

        public override void MapToInput(MapContext<TDatabase> mapContext, object output, object input)
        {
            var outputValue = OutputSelector((TParentOutput)output);

            var outputId = outputValue == null ? null : Mapper.PrimaryKey.OutputSelector(outputValue);
            dbIdSelector.SetProperty(input, outputId);
        }

        public override string ToString()
        {
            return string.Format("EntityRefMapping({0}, {1}, {2})", dbIdSelector, dbSelector, outputSelector);
        }
    }
}